﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Asol.Reporting.Green.Components;
using Asol.Reporting.Support;

namespace Asol.Reporting.Green.Forms
{
    public partial class Test1Form : Form
    {
        public Test1Form()
        {
            InitializeComponent();
            this._TestPanel.PaintToBuffer += new PaintEventHandler(_TestPanel_PaintToBuffer);
        }
        Rectangle TestArea { get { return new Rectangle(30, 30, 260, 50); } }
        void _TestPanel_PaintToBuffer(object sender, PaintEventArgs e)
        {

            this.testDots(e.Graphics);
            // this.testSquare(e.Graphics);
            // this.testLabel(e.Graphics);
            // this.testGrad(e.Graphics);
            // this.testSquare(e.Graphics);
            // this.testRect(e.Graphics);
            this.testPainter(e.Graphics);
        }

        private void testDots(Graphics graphics)
        {
            graphics.InterpolationMode = InterpolationMode.Low;
            graphics.SmoothingMode = SmoothingMode.None;
            graphics.PixelOffsetMode = PixelOffsetMode.None;
            using (Pen pen = new Pen(Color.Black))
            using (SolidBrush br = new SolidBrush(Color.Black))
            {
                for (int y = 0; y < _TestPanel.Height; y += 10)
                    for (int x = 0; x < _TestPanel.Width; x += 10)
                    {
                        graphics.FillRectangle(br, new Rectangle(x, y, 1, 1));
                    }

                Rectangle area = TestArea;

                area.Y = 100;
                br.Color = Color.FromArgb(128, Color.LightSkyBlue);
                graphics.FillRectangle(br, area);

                area.Y = 170;
                pen.Color = Color.FromArgb(128, Color.LightSkyBlue);
                graphics.DrawRectangle(pen, area);

                area.Y = 240;
                pen.Color = Color.FromArgb(128, Color.Red);
                pen.Width = 3f;
                graphics.DrawRectangle(pen, area);
            }
        }
        private void testPainter(Graphics graphics)
        {
            PaintTabFrameArgs args = new PaintTabFrameArgs();
            args.ColorBorder = Color.FromArgb(224, 96, 160, 160); // (224, 64, 64, 216);
            args.ColorTab = Color.FromArgb(224, 200, 240, 240);
            args.ColorEdge = Color.FromArgb(224, 160, 240, 240);
            args.ColorInner = Color.FromArgb(64, 64, 255, 255);
            args.FrameBounds = TestArea;
            args.TabBounds = new Rectangle(args.FrameBounds.X + 25, args.FrameBounds.Y, 50, 26);
            args.TabCornerSize = 3;
            args.EdgeWidth = 2;
            Painter.PaintTabFrame(graphics, args);

            args.TabCornerSize = 3;

            args.FrameBounds = new Rectangle(args.FrameBounds.X + args.FrameBounds.Width + 10, args.FrameBounds.Y + 10, args.FrameBounds.Width, 100);
            args.TabBounds = new Rectangle(args.FrameBounds.X + 103, args.FrameBounds.Y - 24, 50, 24);
            // args.TabBounds = new Rectangle(args.FrameBounds.X - 50, args.FrameBounds.Y + 5, 50, 26);
            args.ColorTab = Color.FromArgb(224, 216, 216, 255);
            args.ColorEdge = Color.FromArgb(224, 196, 196, 236);
            args.ColorInner = Color.FromArgb(64, 196, 196, 236);
            args.EdgeWidth = 1;
            Painter.PaintTabFrame(graphics, args);

            // args.FrameBounds = new Rectangle(args.FrameBounds.X + args.FrameBounds.Width + 10, args.FrameBounds.Y + 10, args.FrameBounds.Width, 100);
            args.TabBounds = new Rectangle(args.FrameBounds.X + 50, args.FrameBounds.Y -26, 50, 26);
            args.ColorTab = Color.FromArgb(224, 216, 255, 216);
            args.ColorEdge = Color.FromArgb(224, 196, 236, 196);
            args.ColorInner = Color.FromArgb(64, 196, 236, 196);
            args.EdgeWidth = 5;
            Painter.PaintTabFrame(graphics, args);

        }

        private void testRect(Graphics graphics)
        {
            Rectangle area = TestArea;
            area.Width += 1;
            area.Height += 1;
            Color color1 = Color.FromArgb(255, 255, 64, 64);
            Color color2 = Color.FromArgb(0, 0, 64, 64);
            int width = 20;
          
            using (Pen pen = new Pen(Color.Black, 1f))
            {
                for (int d = 0; d < width; d++)
                {
                    area.Inflate(-1, -1);
                    float ratio = ((float)d) / ((float)(width - 1));
                    pen.Color = color1.Morph(color2, ratio);
                    graphics.DrawRectangle(pen, area);
                }
            }

        }
        private void testLabel(Graphics graphics)
        {
            Rectangle area = TestArea;
          
            using (SolidBrush sb = new SolidBrush(Color.DarkBlue))
            {
                int y = area.Y - 20;
                int x = area.X + 10;
                while (y < area.Bottom)
                {
                    graphics.DrawString("První malý pokus o text, který by měl reprezentovat překrytí barvy podkladového textu štětcem naneseným navrch.", this._TestPanel.Font, sb, x, y);
                    y += 15;
                    x += 1;
                }
            }
        }
        private void testGrad(Graphics graphics)
        {
            Rectangle area = TestArea;
            
            Color color1 = Color.FromArgb(255, 255, 64, 64);
            Color color2 = Color.FromArgb(255, 64, 255, 64);
            float a = 0f;
            int b = 6;
            int q = 0;
            Rectangle a1 = new Rectangle(area.X, area.Y, area.Width, b);
            GraphicsPath path1 = new GraphicsPath();
            path1.AddPolygon(new Point[] {
                new Point(a1.X, a1.Y),
                new Point(a1.Right - q, a1.Y),
                new Point(a1.Right - q - b, a1.Bottom - q),
                new Point(a1.X + b, a1.Bottom - q),
                new Point(a1.X, a1.Y)});
            path1.CloseFigure();
            using (LinearGradientBrush lgb = CreateGradient(a1.ShiftBy(-1, -1), color1, color2, GradientDirection.Down))
            {
                graphics.FillPath(lgb, path1);
                Rectangle sqr = a1.Center().CreateRectangleFromCenter(3 * b);
                graphics.FillRectangle(lgb, sqr);
            }

            Rectangle a2 = new Rectangle(area.Right - b, area.Y, b, area.Height);
            GraphicsPath path2 = new GraphicsPath();
            path2.AddPolygon(new Point[] {
                new Point(a2.Right - q, a2.Y),
                new Point(a2.Right - q, a2.Bottom - q),
                new Point(a2.X, a2.Bottom - q - b),
                new Point(a2.X, a2.Y + b),
                new Point(a2.Right - q, a2.Y)});
            path2.CloseFigure();
            using (LinearGradientBrush lgb = CreateGradient(a2, color1, color2, GradientDirection.Left))
            {
                graphics.FillPath(lgb, path2);
                Rectangle sqr = a2.Center().CreateRectangleFromCenter(3 * b);
                graphics.FillRectangle(lgb, sqr);
            }

            Rectangle a3 = new Rectangle(area.X, area.Bottom - b, area.Width, b);
            GraphicsPath path3 = new GraphicsPath();
            path3.AddPolygon(new Point[] {
                new Point(a3.X + b, a3.Y),
                new Point(a3.Right - q - b, a3.Y),
                new Point(a3.Right - q, a3.Bottom - q),
                new Point(a3.X, a3.Bottom - q),
                new Point(a3.X + b, a3.Y)});
            path3.CloseFigure();
            using (LinearGradientBrush lgb = CreateGradient(a3.ShiftBy(-1, -1), color1, color2, GradientDirection.Up))
            {
                graphics.FillPath(lgb, path3);
                Rectangle sqr = a3.Center().CreateRectangleFromCenter(3 * b);
                graphics.FillRectangle(lgb, sqr);
            }

            Rectangle a4 = new Rectangle(area.X, area.Y, b, area.Height);
            GraphicsPath path4 = new GraphicsPath();
            path4.AddPolygon(new Point[] {
                new Point(a4.X, a4.Y),
                new Point(a4.X + b, a4.Y + b),
                new Point(a4.X + b, a4.Bottom - q - b),
                new Point(a4.X, a4.Bottom - q),
                new Point(a4.X, a4.Y)});
            path4.CloseFigure();
            using (LinearGradientBrush lgb = CreateGradient(a4.ShiftBy(-1, -1), color1, color2, GradientDirection.Right))
            {
                graphics.FillPath(lgb, path4);
                Rectangle sqr = a4.Center().CreateRectangleFromCenter(3 * b);
                graphics.FillRectangle(lgb, sqr);
            }

            Rectangle a5 = area.Center().CreateRectangleFromCenter(10);
            Rectangle a6 = area.Center().CreateRectangleFromCenter(20);
            using (LinearGradientBrush lgb = new LinearGradientBrush(a5, color1, color2, a + 30f))
            {
                graphics.FillRectangle(lgb, a6);
            }
            using (SolidBrush br = new SolidBrush(Color.FromArgb(128, 128, 128, 128)))
            {
                graphics.FillRectangle(br, a5);
            }

        }
        private void testBorder(Graphics graphics)
        {
            Rectangle area = TestArea;

            Painter.PaintBorder(graphics, area, BorderStyle.Fixed3D);
        }
        private void testQ(Graphics graphics)
        {
            Rectangle area = new Rectangle(50, 50, 100, 100);
            int w = area.Width / 3;

            Rectangle area1 = new Rectangle(area.X, area.Y, w, area.Height);
            using (LinearGradientBrush lgb = new LinearGradientBrush(area1, Color.FromArgb(0, Color.BlueViolet), Color.FromArgb(255, Color.BlueViolet), 90f))
            {
                graphics.FillRectangle(lgb, area1);
            }

            Rectangle area2 = new Rectangle(area.X + w, area.Y, w, area.Height);
            using (LinearGradientBrush lgb = new LinearGradientBrush(area2, Color.FromArgb(0, Color.BlueViolet), Color.FromArgb(255, Color.BlueViolet), 90f))
            {
                lgb.SetBlendTriangularShape(0.25f, 0.95f);         // Triangl: přechod od krajů ke středu je lineární.        1: kde je střed = barva (2);  2: síla barvy (2) v pozici středu
                graphics.FillRectangle(lgb, area2);
            }

            Rectangle area3 = new Rectangle(area.X + w + w, area.Y, w, area.Height);
            using (LinearGradientBrush lgb = new LinearGradientBrush(area3, Color.FromArgb(0, Color.BlueViolet), Color.FromArgb(255, Color.BlueViolet), 90f))
            {
                lgb.SetSigmaBellShape(0.25f, 0.95f);               // SigmaBell: přechod od krajů ke středu je sinusovitý.    1: kde je střed = barva (2);  2: síla barvy (2) v pozici středu
                graphics.FillRectangle(lgb, area3);
            }
        }
        private void testSquare(Graphics graphics)
        {
            Color color1 = Color.FromArgb(255, 255, 64, 64);
            Color color2 = Color.FromArgb(255, 64, 255, 64);

            float angle = 0f; float aa = 30f;
            for (int y = 20; y < 30; y += 50)
            {
                for (int x = 20; x < 480; x += 20)
                {
                    this.test1(graphics, new Rectangle(x, y, 8, 8), color1, color2, angle);
                    this.test1(graphics, new Rectangle(x, y + 20, 8, 8), color2, color1, angle);
                    angle += aa;
                }
            }

            int gx = 20;
            int gy = 80;
            this.test2(graphics, new Rectangle(gx, gy, 8, 8), color1, color2, GradientDirection.Right); gx += 20;
            this.test2(graphics, new Rectangle(gx, gy, 8, 8), color1, color2, GradientDirection.Down); gx += 20;
            this.test2(graphics, new Rectangle(gx, gy, 8, 8), color1, color2, GradientDirection.Left); gx += 20;
            this.test2(graphics, new Rectangle(gx, gy, 8, 8), color1, color2, GradientDirection.Up); gx += 20;

        }

        private void test1(Graphics graphics, Rectangle area, Color color1, Color color2, float angle)
        {
            using (LinearGradientBrush lgb = new LinearGradientBrush(area, color1, color2, angle))
            using (SolidBrush sb = new SolidBrush(Color.FromArgb(128,160,160,160)))
            {
                Rectangle area2 = area;
                area2.Inflate(4, 4);
                graphics.FillRectangle(lgb, area2);
                graphics.FillRectangle(sb, area);
            }
        }
        private void test2(Graphics graphics, Rectangle area, Color color1, Color color2, GradientDirection direction)
        {
            using (LinearGradientBrush lgb = CreateGradient(area, color1, color2, direction))
            using (SolidBrush sb = new SolidBrush(Color.FromArgb(128, 160, 160, 160)))
            {
                Rectangle area2 = area;
                area2.Inflate(4, 4);
                graphics.FillRectangle(lgb, area2);
                graphics.FillRectangle(sb, area);
            }
        }
        private static LinearGradientBrush CreateGradient(Rectangle area, Color colorFrom, Color colorTo, GradientDirection direction)
        {
            Rectangle shft;
            switch (direction)
            {
                case GradientDirection.Right:
                    return new LinearGradientBrush(area, colorFrom, colorTo, 0f);
                case GradientDirection.Down:
                    return new LinearGradientBrush(area, colorFrom, colorTo, 90f);
                case GradientDirection.Left:
                    // Tady už má LinearGradientBrush problém, pokud bych vrátil gradient jako dosud, 
                    // pak bude posunutý o 1px doprava. Takže posunu area o 1px doleva:
                    shft = new Rectangle(area.X - 1, area.Y, area.Width, area.Height);
                    return new LinearGradientBrush(shft, colorFrom, colorTo, 180f);
                case GradientDirection.Up:
                    // Tady už má LinearGradientBrush problém, pokud bych vrátil gradient jako dosud, 
                    // pak bude posunutý o 1px doprava. Takže posunu area o 1px doleva:
                    shft = new Rectangle(area.X - 1, area.Y, area.Width, area.Height);
                    return new LinearGradientBrush(area, colorTo, colorFrom, 90f);
            }
            return new LinearGradientBrush(area, colorFrom, colorTo, 0f);
        }
        public enum GradientDirection
        {
            None,
            /// <summary>
            /// Doprava: na levé souřadnici bude barva "colorFrom" (spolehlivě), 
            /// doprava bude směřovat k barvě "colorTo"
            /// (možná na poslední souřadnici vpravo nebude požadovaná barva, ale barva o stupeň bližší k "colorFrom").
            /// </summary>
            Right,
            /// <summary>
            /// Dolů: na horní souřadnici bude barva "colorFrom" (spolehlivě), 
            /// dolů bude směřovat k barvě "colorTo"
            /// (možná na poslední souřadnici dole nebude požadovaná barva, ale barva o stupeň bližší k "colorFrom").
            /// </summary>
            Down,
            /// <summary>
            /// Doleva: na pravé souřadnici bude barva "colorFrom" (spolehlivě), 
            /// doleva bude směřovat k barvě "colorTo"
            /// (možná na poslední souřadnici vlevo nebude požadovaná barva, ale barva o stupeň bližší k "colorFrom").
            /// </summary>
            Left,
            /// <summary>
            /// Nahoru: na dolní souřadnici bude barva "colorFrom" (spolehlivě), 
            /// nahoru bude směřovat k barvě "colorTo"
            /// (možná na poslední souřadnici nahoře nebude požadovaná barva, ale barva o stupeň bližší k "colorFrom").
            /// </summary>
            Up
        }

        private static Rectangle rq(Rectangle r)
        {
            Rectangle q = new Rectangle(r.X - 1, r.Y - 1, r.Width + 1, r.Height + 1);
            q = new Rectangle(r.X, r.Y, r.Width + 1, r.Height + 1);
            return q;
        }
    }
}
